package sing.core.base

import android.os.Bundle
import androidx.annotation.LayoutRes
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.ViewModelStoreOwner
import sing.core.ext.getVmClazz
import sing.core.network.manager.NetState
import sing.core.network.manager.NetworkStateManager
import sing.core.util.AppActivityManager
import com.gyf.immersionbar.ImmersionBar
import android.R
import androidx.appcompat.app.AlertDialog
import sing.core.dialog.CustomDialog
import sing.core.ext.dismissLoadingExt
import sing.core.ext.showLoadingExt
import sing.core.util.MMkvUtil
import sing.core.util.NetUtil


/**
 * 描述　: ViewModelActivity基类，把ViewModel注入进来了
 */


abstract class BaseActivity<VM : BaseViewModel, DB : ViewDataBinding>(@LayoutRes private val layoutId: Int, private val varViewModelId: Int? = null) : AppCompatActivity() {

    lateinit var vm: VM
    fun isVMInitialised() = ::vm.isInitialized

    lateinit var db: DB
    fun isDBInitialised() = ::db.isInitialized

    private var mImmersionBar: ImmersionBar? = null

    open fun initView(savedInstanceState: Bundle?){}

    open fun showLoading(message: String = ""){
        showLoadingExt(message)
    }
    open fun dismissLoading(){
        dismissLoadingExt()
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        when(NetUtil.getNetWorkStart(this)){
            0 -> MMkvUtil().network = "mobile"
            1 -> MMkvUtil().network = "no"
            2 -> MMkvUtil().network = "wifi"
        }

        AppActivityManager.add(this)
        db = DataBindingUtil.setContentView(this, layoutId)

        init(savedInstanceState)

        // 绑定 v 和 vm
        if (varViewModelId != null) {
            db.setVariable(varViewModelId, vm)
        }
        // 让 LiveData 和 xml 可以双向绑定
        db.lifecycleOwner = this

        initData()
    }

    private fun init(savedInstanceState: Bundle?) {
        vm = createViewModel(this)
//         让 vm 可以感知 v 的生命周期
//        lifecycle.addObserver(vm)

        registerUiChange()
        initView(savedInstanceState)
        createObserver()
        NetworkStateManager.instance.mNetworkStateCallback.observeInActivity(this, Observer {
            onNetworkStateChanged(it)
        })

        initImmersionBar()
    }

    override fun onDestroy() {
        super.onDestroy()
        // 界面销毁时移除 vm 的生命周期感知
//        lifecycle.removeObserver(vm)
        db.unbind()
    }

    /**
     * 网络变化监听 子类重写
     */
    open fun onNetworkStateChanged(netState: NetState) {}
    open fun initData() {}

    /**
     * 创建LiveData数据观察者
     */
    open fun createObserver(){}

    /**
     * 创建viewModel
     */
    private fun createViewModel(viewModelStoreOwner: ViewModelStoreOwner): VM {
//        val modelClass: Class<VM>
//        val type: Type? = javaClass.genericSuperclass
//        modelClass = (if (type is ParameterizedType) {
//            type.actualTypeArguments[1] as Class<VM>
//        } else {
//            //如果没有指定泛型参数，则默认使用BaseViewModel
//            BaseViewModel::class.java
//        }) as Class<VM>
//        return ViewModelProvider(
//            viewModelStoreOwner,
//            ViewModelProvider.AndroidViewModelFactory(BaseApp.getInstance())
//        ).get(modelClass)


        return ViewModelProvider(this).get(getVmClazz(this))
    }


    /**
     * 注册UI 事件
     */
    private fun registerUiChange() {
        //显示弹窗
        vm.loadingChange.showDialog.observeInActivity(this, Observer {
            showLoading(it)
        })
        //关闭弹窗
        vm.loadingChange.dismissDialog.observeInActivity(this, Observer {
            dismissLoading()
        })
    }

    /**
     * 将非该Activity绑定的ViewModel添加 loading回调 防止出现请求时不显示 loading 弹窗bug
     * @param viewModels Array<out BaseViewModel>
     */
    protected fun addLoadingObserve(vararg viewModels: BaseViewModel){
        viewModels.forEach {viewModel ->
            //显示弹窗
            viewModel.loadingChange.showDialog.observeInActivity(this, Observer {
                showLoading(it)
            })
            //关闭弹窗
            viewModel.loadingChange.dismissDialog.observeInActivity(this, Observer {
                dismissLoading()
            })
        }
    }

    fun showErrorDialog(message: String,isClose:Boolean = true) {
        val d = CustomDialog(this)
        d.setMsg(message)
        d.hintCancel()
        d.setCancelable(false)
        d.addListener(object : CustomDialog.OnClickListener{
            override fun confirm(dialog: AlertDialog?) {
                super.confirm(dialog)
                if (isClose){
                    onBackPressed()
                }
            }
        })
        d.show()
    }

    fun showErrorDialog(message: String,listener:CustomDialog.OnClickListener) {
        val d = CustomDialog(this)
        d.setMsg(message)
        d.hintCancel()
        d.setCancelable(false)
        d.addListener(listener)
        d.show()
    }

    /**
     * 初始化沉浸式
     */
    protected open fun initImmersionBar() {
//        ImmersionBar.with(this)
//            .transparentStatusBar() //透明状态栏，不写默认透明色
//            .transparentNavigationBar() //透明导航栏，不写默认黑色(设置此方法，fullScreen()方法自动为true)
//            .transparentBar() //透明状态栏和导航栏，不写默认状态栏为透明色，导航栏为黑色（设置此方法，fullScreen()方法自动为true）
//            .statusBarColor(R.color.colorPrimary) //状态栏颜色，不写默认透明色
//            .navigationBarColor(R.color.colorPrimary) //导航栏颜色，不写默认黑色
//            .barColor(R.color.colorPrimary) //同时自定义状态栏和导航栏颜色，不写默认状态栏为透明色，导航栏为黑色
//            .statusBarAlpha(0.3f) //状态栏透明度，不写默认0.0f
//            .navigationBarAlpha(0.4f) //导航栏透明度，不写默认0.0F
//            .barAlpha(0.3f) //状态栏和导航栏透明度，不写默认0.0f
//            .statusBarDarkFont(true) //状态栏字体是深色，不写默认为亮色
//            .navigationBarDarkIcon(true) //导航栏图标是深色，不写默认为亮色
//            .autoDarkModeEnable(true) //自动状态栏字体和导航栏图标变色，必须指定状态栏颜色和导航栏颜色才可以自动变色哦
//            .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色，必须指定状态栏颜色才可以自动变色哦
//            .autoNavigationBarDarkModeEnable(true, 0.2f) //自动导航栏图标变色，必须指定导航栏颜色才可以自动变色哦
//            .flymeOSStatusBarFontColor(R.color.btn3) //修改flyme OS状态栏字体颜色
//            .fullScreen(true) //有导航栏的情况下，activity全屏显示，也就是activity最下面被导航栏覆盖，不写默认非全屏
//            .hideBar(BarHide.FLAG_HIDE_BAR) //隐藏状态栏或导航栏或两者，不写默认不隐藏
//            .addViewSupportTransformColor(toolbar) //设置支持view变色，可以添加多个view，不指定颜色，默认和状态栏同色，还有两个重载方法
//            .titleBar(view) //解决状态栏和布局重叠问题，任选其一
//            .titleBarMarginTop(view) //解决状态栏和布局重叠问题，任选其一
//            .statusBarView(view) //解决状态栏和布局重叠问题，任选其一
//            .fitsSystemWindows(true) //解决状态栏和布局重叠问题，任选其一，默认为false，当为true时一定要指定statusBarColor()，不然状态栏为透明色，还有一些重载方法
//            .supportActionBar(true) //支持ActionBar使用
//            .statusBarColorTransform(R.color.orange) //状态栏变色后的颜色
//            .navigationBarColorTransform(R.color.orange) //导航栏变色后的颜色
//            .barColorTransform(R.color.orange) //状态栏和导航栏变色后的颜色
//            .removeSupportView(toolbar) //移除指定view支持
//            .removeSupportAllView() //移除全部view支持
//            .navigationBarEnable(true) //是否可以修改导航栏颜色，默认为true
//            .navigationBarWithKitkatEnable(true) //是否可以修改安卓4.4和emui3.x手机导航栏颜色，默认为true
//            .navigationBarWithEMUI3Enable(true) //是否可以修改emui3.x手机导航栏颜色，默认为true
//            .keyboardEnable(true) //解决软键盘与底部输入框冲突问题，默认为false，还有一个重载方法，可以指定软键盘mode
//            .keyboardMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE) //单独指定软键盘模式
//            .setOnKeyboardListener(OnKeyboardListener { isPopup, keyboardHeight ->
//
//                //软键盘监听回调，keyboardEnable为true才会回调此方法
//                LogUtils.e(isPopup) //isPopup为true，软键盘弹出，为false，软键盘关闭
//            })
//            .setOnNavigationBarListener(onNavigationBarListener) //导航栏显示隐藏监听，目前只支持华为和小米手机
//            .setOnBarListener(OnBarListener) //第一次调用和横竖屏切换都会触发，可以用来做刘海屏遮挡布局控件的问题
//            .addTag("tag") //给以上设置的参数打标记
//            .getTag("tag") //根据tag获得沉浸式参数
//            .reset() //重置所以沉浸式参数
//            .init() //必须调用方可应用以上所配置的参数

        mImmersionBar = ImmersionBar.with(this)
        mImmersionBar!!
            .statusBarDarkFont(true, 1.0f)
            .navigationBarColor(R.color.white) //导航栏颜色，不写默认黑色
            .init()
    }

    fun setDark(boolean: Boolean){
        if (mImmersionBar == null){
            mImmersionBar = ImmersionBar.with(this)
        }
        if (boolean){ // 黑色文字
            mImmersionBar!!
                .statusBarDarkFont(true, 1.0f)
                .navigationBarColor(R.color.white)
                .init()
        }else{ // 白色文字
            mImmersionBar!!
                .statusBarDarkFont(false, 1.0f)
                .navigationBarColor(R.color.white)
                .init()
        }
    }
}